//
// Created by lexwu on 2017/3/30.
//
#include <jni.h>
#include <stdlib.h>
#include <string>
#include "JniUtils.h"


/**
 * 把java的string转化成c的字符串
 */
std::string Jstring2string(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");  //String
    jstring strencode = env->NewStringUTF("GB2312"); //"gb2312"
    jmethodID mid = env->GetMethodID(clsstring, "getBytes",
                                     "(Ljava/lang/String;)[B"); //getBytes(Str);
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid,
                                                         strencode); // String .getByte("GB2312");
    jsize alen = env->GetArrayLength(barr);
    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);         //"\0"
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);  //释放内存空间
    return rtn;
}

/**
 * C字符串转java字符串
 */
jstring Str2Jstring(JNIEnv *env, const char *pStr) {
    int strLen = strlen(pStr);
    jclass jstrObj = env->FindClass("java/lang/String");
    jmethodID methodId = env ->GetMethodID(jstrObj, "<init>", "([BLjava/lang/String;)V");
    jbyteArray byteArray = env ->NewByteArray(strLen);
    jstring encode = env ->NewStringUTF("utf-8");
    env ->SetByteArrayRegion(byteArray, 0, strLen, (jbyte *) pStr);
    return (jstring) env ->NewObject(jstrObj, methodId, byteArray, encode);
}


std::string getDeviceId(JNIEnv *env, jobject mContext) {
    if(mContext == 0){
        LOGI("[+] Error: Context is 0");
    }
    jclass cls_context = env->FindClass("android/content/Context");
    if(cls_context == 0){
        LOGI("[+] Error: FindClass <android/content/Context> Error");
    }

    jmethodID getSystemService = (env)->GetMethodID(cls_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
    if(getSystemService == 0){
        LOGI("[+] Error: GetMethodID failed");
    }

    jfieldID TELEPHONY_SERVICE = (env)->GetStaticFieldID(cls_context, "TELEPHONY_SERVICE", "Ljava/lang/String;");
    if(TELEPHONY_SERVICE == 0){
        LOGI("[+] Error: GetStaticFieldID Failed");
    }

    jstring telephonystr = (jstring)(env)->GetStaticObjectField(cls_context, TELEPHONY_SERVICE);
    jobject telephonymanager = ((env)->CallObjectMethod(mContext, getSystemService, telephonystr));
    if(telephonymanager == 0){
        LOGI("[+] Error: CallObjectMethod failed");
    }

    jclass cls_TelephoneManager = (env)->FindClass( "android/telephony/TelephonyManager");
    if(cls_TelephoneManager == 0){
        LOGI("[+] Error: FindClass TelephoneManager failed");
    }

    jmethodID getDeviceId = ((env)->GetMethodID(cls_TelephoneManager, "getDeviceId", "()Ljava/lang/String;"));
    if(getDeviceId == 0){
        LOGI("[+] Error: GetMethodID getDeviceID failed");
    }

    jobject DeviceID = (env)->CallObjectMethod(telephonymanager,getDeviceId);
    (env)->DeleteLocalRef(cls_context);
    (env)->DeleteLocalRef(telephonymanager);
    return Jstring2string(env,((jstring)DeviceID));
}

std::string getMac(JNIEnv *env, jobject mContext){
    if(mContext == 0){
        LOGI("[+] Error: Context is 0");
    }
    jclass cls_context = env->FindClass("android/content/Context");
    if(cls_context == 0){
        LOGI("[+] Error: FindClass <android/content/Context> Error");
    }
    jmethodID getSystemService = (env)->GetMethodID(cls_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
    if(getSystemService == 0){
        LOGI("[+] Error: GetMethodID failed");
    }
    //macID
    jfieldID WIFI_SERVICE = (env)->GetStaticFieldID(cls_context, "WIFI_SERVICE", "Ljava/lang/String;");
    if(WIFI_SERVICE == 0){
        LOGI("[+] Error: GetStaticFieldID Failed");
    }
    jstring wifistr = (jstring)(env)->GetStaticObjectField(cls_context, WIFI_SERVICE);
    jobject wifimanager = ((env)->CallObjectMethod(mContext, getSystemService, wifistr));
    if(wifimanager == 0){
        LOGI("[+] Error: CallObjectMethod failed");
    }
    jclass cls_WifiManager = (env)->FindClass( "android/net/wifi/WifiManager");
    if(cls_WifiManager == 0){
        LOGI("[+] Error: FindClass cls_WifiManager failed");
    }
    jmethodID getWifiId = ((env)->GetMethodID(cls_WifiManager, "getConnectionInfo", "()Landroid/net/wifi/WifiInfo;"));

    jobject wifiInfo = env->CallObjectMethod(wifimanager,getWifiId);
    jclass wifiInfoclass = env->GetObjectClass(wifiInfo);
    jmethodID getMacId = env->GetMethodID(wifiInfoclass,"getMacAddress","()Ljava/lang/String;");
    jobject MacID = env->CallObjectMethod(wifiInfo,getMacId);
    (env)->DeleteLocalRef(cls_context);
    return Jstring2string(env,((jstring)MacID));
}